"""
内容：定义一个工厂类接口，让工厂子类来创建一系类相关或相互依赖的对象。

例：生产一部手机，需要手机壳、CPU、操作系统三类对象进行组装，其中每类对象都有不同的种类。对每个具体工厂，分别生产一部手机所需要的三个对象。

相比工厂方法模式，抽象工厂模式中的每个具体工厂都生产一套产品。

角色：
    抽象工厂角色（Creator）
    具体工厂角色（Concrete Creator）
    抽象产品角色（Product）
    具体产品角色（Concrete Product）
    客户端（Client）

其实就是：
1、先创建抽象产品（手机壳、cpu、操作系统）
2、创建抽象产品具体的产品（比如，苹果手机壳，华为手机壳）
3、创建抽象工厂，手机加工需要（手机壳、cpu、操作系统）
4、创建具体工厂，添加对应的手机配置
5、创建客户端，传递具体工厂来实现手机的组装
"""

from abc import ABCMeta, abstractmethod


# ------抽象产品------
class PhoneShell(metaclass=ABCMeta):
    """手机壳"""

    @abstractmethod
    def show_shell(self):
        pass


class CPU(metaclass=ABCMeta):
    """CPU"""

    @abstractmethod
    def show_cpu(self):
        pass


class OS(metaclass=ABCMeta):
    """系统"""

    @abstractmethod
    def show_os(self):
        pass


# ------抽象工厂------
class PhoneFactory(metaclass=ABCMeta):
    """手机加工"""

    @abstractmethod
    def make_shell(self):  # 手机壳
        pass

    @abstractmethod
    def make_cpu(self):  # cpu
        pass

    @abstractmethod
    def make_os(self):  # 系统
        pass


# ------具体产品------
class SmallShell(PhoneShell):
    def show_shell(self):
        print("普通手机小手机壳")


class AppleShell(PhoneShell):
    def show_shell(self):
        print("苹果手机壳")


class SnapDragonCPU(CPU):
    def show_cpu(self):
        print("骁龙CPU")


class AppleCPU(CPU):
    def show_cpu(self):
        print("苹果CPU")


class Android(OS):
    def show_os(self):
        print("Android系统")


class IOS(OS):
    def show_os(self):
        print("iOS系统")


# ------具体工厂------
class HuaweiFactory(PhoneFactory):
    def make_cpu(self):
        return SnapDragonCPU()

    def make_os(self):
        return Android()

    def make_shell(self):
        return SmallShell()


class IPhoneFactory(PhoneFactory):
    def make_cpu(self):
        return AppleCPU()

    def make_os(self):
        return IOS()

    def make_shell(self):
        return AppleShell()


# ------客户端------
class Phone:
    def __init__(self, cpu, os, shell):
        self.cpu = cpu
        self.os = os
        self.shell = shell

    def show_info(self):
        print("手机信息:")
        self.cpu.show_cpu()
        self.os.show_os()
        self.shell.show_shell()


def make_phone(factory):
    cpu = factory.make_cpu()
    os = factory.make_os()
    shell = factory.make_shell()
    return Phone(cpu, os, shell)


p1 = make_phone(HuaweiFactory())
p1.show_info()
